import * as THREE from "three"
import initRenderer from "./core/renderer";
import initScene from "./core/scene";
import { LineGeometry } from "three/examples/jsm/lines/LineGeometry.js";

import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry.js';
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2.js';
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
import { BufferGeometry } from "three";


class Box {
    private scene;
    private camera;
    private renderer;
    private container;
    private pointNum = 100;
    private num = 10;//从曲线上获取点数量
    private index = 20;//取点索引位置
    private geometry_short;
    private points;

    constructor(container) {
        this.container = container;
        this.scene = new THREE.Scene();
        this.init();
    }
    init() {
        // 初始化渲染器和相机
        let { renderer, camera, render } = initRenderer({ scene: this.scene, container: this.container });
        this.renderer = renderer;
        this.camera = camera;
        this.renderer.setClearColor("black");

        // 初始化场景
        initScene({ scene: this.scene, container: this.container, renderer: this.renderer, camera: this.camera });

        //初始化模型
        this.initObjects();

        // 开始渲染
        render();
    }

    initObjects() {
        this.createLine();
        this.animate();
    }

    //绘制
    createLine() {
        var geometry = new THREE.BufferGeometry();
        // 三维样条曲线
        var curve = new THREE.CatmullRomCurve3([
            new THREE.Vector3(100, 0, -100),
            new THREE.Vector3(0, 80, 0),
            new THREE.Vector3(-100, 0, 100),
        ]);
        //曲线上等间距返回多个顶点坐标
        this.points = curve.getSpacedPoints(100); //分段数100，返回101个顶点
        // setFromPoints方法从points中提取数据赋值给attributes.position
        geometry.setFromPoints(this.points);
        var material = new THREE.LineBasicMaterial({
            color: 0x006666,
        });
        var line = new THREE.Line(geometry, material);
        this.scene.add(line);

        const points_short = this.points.slice(this.index, this.index + this.num); //从曲线上获取一段
        var curve = new THREE.CatmullRomCurve3(points_short);
        var newPoints2 = curve.getSpacedPoints(100);//获取更多的点数
        this.geometry_short = new BufferGeometry();
        this.geometry_short.setFromPoints(newPoints2);

        // 批量计算所有顶点比例
        const percentArr = [];
        for (let i = 0; i < newPoints2.length; i++) {
            percentArr.push(i / newPoints2.length);
        }
        var percentAttribue = new THREE.BufferAttribute(new Float32Array(percentArr), 1);
        this.geometry_short.attributes.percent = percentAttribue;

        // 批量计算所有顶点颜色数据
        var colorArr = [];
        for (var i = 0; i < newPoints2.length; i++) {
            var color1 = new THREE.Color(0x006666); //轨迹线颜色 青色
            var color2 = new THREE.Color(0xffff00); //黄色
            var color = color1.lerp(color2, i / newPoints2.length)
            colorArr.push(color.r, color.g, color.b);
        }
        // 设置几何体顶点颜色数据
        this.geometry_short.attributes.color = new THREE.BufferAttribute(new Float32Array(colorArr), 3);

        var PointsMaterial = new THREE.PointsMaterial({
            size: 5.0, //点大小
            vertexColors: true
        });

        var flyPoints = new THREE.Points(this.geometry_short, PointsMaterial);
        this.scene.add(flyPoints);
        // 修改点材质的着色器源码(注意：不同版本细节可能会稍微会有区别，不过整体思路是一样的)
        PointsMaterial.onBeforeCompile = function (shader) {
            // 顶点着色器中声明一个attribute变量:百分比
            shader.vertexShader = shader.vertexShader.replace(
                'void main() {',
                [
                    'attribute float percent;', //顶点大小百分比变量，控制点渲染大小
                    'void main() {',
                ].join('\n') // .join()把数组元素合成字符串
            );
            // 调整点渲染大小计算方式
            shader.vertexShader = shader.vertexShader.replace(
                'gl_PointSize = size;',
                [
                    'gl_PointSize = percent * size;',
                ].join('\n') // .join()把数组元素合成字符串
            );
        };

    }

    animate() {
        var indexMax = this.pointNum - this.num; //飞线取点索引范围
        if (this.index > indexMax) {
            this.index = 0;
        }
        this.index += 1
        const points2 = this.points.slice(this.index, this.index + this.num); //从曲线上获取一段
        var curve = new THREE.CatmullRomCurve3(points2);
        var newPoints2 = curve.getSpacedPoints(100); //获取更多的点数
        this.geometry_short.setFromPoints(newPoints2);

        requestAnimationFrame(this.animate.bind(this));
    }
}

export default Box;